package com.bing.java.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 
 * @author bing
 *
 * 2019年11月9日 上午11:18:39
 * 
 * wait() notify() notifyAll()
调用 wait() 使得线程等待某个条件满足，线程在等待时会被挂起，当其他线程的运行使得这个条件满足时，其它线程会调用 notify() 或者 notifyAll() 来唤醒挂起的线程。
它们都属于 Object 的一部分，而不属于 Thread。
只能用在同步方法或者同步控制块中使用，否则会在运行时抛出 IllegalMonitorStateException。
使用 wait() 挂起期间，线程会释放锁。这是因为，如果没有释放锁，那么其它线程就无法进入对象的同步方法或者同步控制块中，那么就无法执行 notify() 或者 notifyAll() 
来唤醒挂起的线程，造成死锁。


	wait() 和 sleep() 的区别
  ● wait() 是 Object 的方法，而 sleep() 是 Thread 的静态方法；
  ● wait() 会释放锁，sleep() 不会。
 */
public class WaitNotifyExample {

	public synchronized void before() {
		System.out.println("before");
		notifyAll();
//		notify();
	}

	public synchronized void after() {
		try {
			wait();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("after");
	}

	/**
	 * 
	 * @param args
	 * 
	 * 先调用after，方法内wait等待，所以after执行不了。另外一个线程调用before方法，执行before，然后释放所有锁notifyAll，即after线程wait结束开始执行after
	 * before  after
	 */
	public static void main(String[] args) {
		ExecutorService executorService = Executors.newCachedThreadPool();
		WaitNotifyExample example = new WaitNotifyExample();
//		WaitNotifyExample example2 = new WaitNotifyExample();     //如果是2个对象，并且上面执行的是notify或者notifyAll方法，那都结果只有before，不同对象释放不了
//		notify();     
//		executorService.execute(() -> example2.before());
		executorService.execute(() -> example.after());
		executorService.execute(() -> example.before());
	}
}
